#!/usr/bin/python
#vim:fileencoding=utf-8
"""
Модуль содержит описание грамматического анализатора Англиского Языка.

Идея такая, анализатор получает на вход строку, в которой каждое слово
это часть речи + форма, такая строка это грамматическая структура
предложения.

На выходе анализатор даёт метод, который получает на вход список базовых
форм слов и выплёвывает построенную по грамматической структуре мысль.
"""

if __name__ == '__main__':
    import os
    import sys
    src_dir = os.path.join('..', '..')
    sys.path.append(src_dir)
    sys.path.append('.')
    

from ply import lex
from ply.lex import TOKEN

from gnTai.aiexception import AIException
from gnTai.usefull_staff.constants import ALL_ALPHABET


#################################################
# 
# Лексика нашего анализатора.
# 
tokens = ['NOUN',
          'VERB',
          'MODAL_VERB',
          'ARTICLE',
          'DOT',
          'COMMA',
          'INTERROGATION_MARK']

form = r'{[^}]*}'
def extract_form(t):
    try:
        t.value = eval(t.value.strip(ALL_ALPHABET))
    except Exception, e:
        raise AIException( "%s In context %s" % (str(e), t.value))
    return t

@TOKEN(r'Noun' + form)
def t_NOUN(t):
    return extract_form(t)

@TOKEN(r'Verb' + form)
def t_VERB(t):
    return extract_form(t)

@TOKEN(r'Article' + form)
def t_ARTICLE(t):
    return extract_form(t)

@TOKEN(r'ModalVerb' + form)
def t_MODAL_VERB(t):
    return extract_form(t)

t_DOT = r'[.]{}'
t_COMMA = r'[,]{}'
t_INTERROGATION_MARK = r'[?]{}'
t_ignore = ' \t'

def t_error(t):
    raise AIException("Illegal construction '%s'" % t)

__Lexer = lex.lex()
Lexer = __Lexer.clone

#################################################
# Грамматика нашего анализатора
#
#
# sentence = statement DOT
# statement = object action
#
#

from ply import yacc

from gnTai.concepts.object import Object
from gnTai.concepts.action import Action
from gnTai.thoughts.thought import Thought
from gnTai.words.noun import Noun
from gnTai.words.verb import Verb


class Builder:
    pass


def p_sentence_statement(p):
    """ sentence : statement DOT"""
    p[0] = Builder()
    p[0].args = p[1].args + 1
    p0 = p[0]
    p1 = p[1]
    def build(arg):
            assert len(arg) == p0.args
            return p1.build(arg[:-1])
    p[0].build = build


def p_statement_object_action(p):
    """ statement : object action """
    p[0] = Builder()
    p[0].args = p[1].args + p[2].args
    p0 = p[0]
    p1 = p[1]
    p2 = p[2]
    def build( arg):
            assert len(arg) == p0.args
            subject = p1.build(arg[:p1.args])
            action = p2.build(arg[p1.args:])
            ret = Thought(subject, action)
            return ret
    p[0].build = build


def p_object_noun(p):
    """ object : NOUN """
    p[0] = Builder()
    p[0].args = 1
    p0 = p[0]
    p1 = p[1]
    def build( arg):
            assert len(arg) == p0.args
            base = arg[0]
            ret = Object(base, **p1)
            return ret
    p[0].build = build

def p_action_verb(p):
    """ action : VERB """
    p[0] = Builder()
    p[0].args = 1
    p0 = p[0]
    p1 = p[1]
    def build(arg):
            assert len(arg) == p0.args
            base = arg[0]
            ret = Action(base, **p1)
            return ret
    p[0].build = build

def p_error(p):
    raise AIException("Wrong grammar form")

Parser = yacc.yacc()

if __name__ == '__main__':
    data = """Noun{} Verb{}."""
    sentence = ("apple", "exist", ".")
    builder = Parser.parse(data)
    print builder.build(sentence)
